package club.riven.distribute;

import club.riven.manager.RedissonManager;
import org.redisson.api.RLock;

import java.util.Collection;
import java.util.concurrent.TimeUnit;

/**
 * 分布式redis锁
 *
 * @author sunyi
 * @date 2020/7/2
 */
public class DistributedRedisLock {
    /**
     * 从配置类中获取redisson对象
     */
    private static final String LOCK_TITLE = "redissonLock:";
    private static final int LOCK_TIME_MINUTES = 2;

    /**
     * 加锁，时间默认2m
     *
     * @param lockName 锁名
     */
    public static RLock acquire(String lockName) {
        return acquire(lockName, LOCK_TIME_MINUTES, TimeUnit.MINUTES);
    }

    /**
     * 获取锁
     *
     * @param lockName 锁名
     */
    public static RLock getLock(String lockName) {
        //声明key对象
        String key = LOCK_TITLE + lockName;
        //获取锁对象
        return RedissonManager.getClient().getLock(key);
    }

    /**
     * 获取锁
     *
     * @param lockNames 锁名
     */
    public static RLock getLock(String... lockNames) {
        if (lockNames == null || lockNames.length < 1) {
            return null;
        }
        //获取锁对象
        RLock[] locks = new RLock[lockNames.length];
        for (int i = 0; i < lockNames.length; i++) {
            String key = LOCK_TITLE + lockNames[i];
            RLock lock = RedissonManager.getClient().getLock(key);
            locks[i] = lock;
        }
        return RedissonManager.getClient().getMultiLock(locks);
    }

    /**
     * 加锁，时间默认2m
     *
     * @param lockName 锁名
     */
    public static RLock acquire(String lockName, long leaseTime, TimeUnit unit) {
        //声明key对象
        String key = LOCK_TITLE + lockName;
        //获取锁对象
        RLock lock = RedissonManager.getClient().getLock(key);
        //加锁，并且设置锁过期时间，防止死锁的产生
        lock.lock(leaseTime, unit);
        return lock;
    }

    /**
     * 加锁，时间默认2m
     *
     * @param lockNames 锁名
     */
    public static RLock acquire(String... lockNames) {
        if (lockNames == null || lockNames.length < 1) {
            return null;
        }
        //获取锁对象
        RLock[] locks = new RLock[lockNames.length];
        for (int i = 0; i < lockNames.length; i++) {
            String key = LOCK_TITLE + lockNames[i];
            RLock lock = RedissonManager.getClient().getLock(key);
            locks[i] = lock;
        }
        RLock lock = RedissonManager.getClient().getMultiLock(locks);
        //加锁，并且设置锁过期时间，防止死锁的产生
        lock.lock(LOCK_TIME_MINUTES, TimeUnit.MINUTES);
        return lock;
    }

    /**
     * 加锁，时间默认2m
     *
     * @param lockNames 锁名
     */
    public static RLock acquire(Collection<String> lockNames) {
        return acquire(lockNames, LOCK_TIME_MINUTES, TimeUnit.MINUTES);
    }

    /**
     * 加锁，时间默认2m
     *
     * @param lockNames 锁名
     */
    public static RLock acquire(Collection<String> lockNames, long leaseTime, TimeUnit unit) {
        if (lockNames == null || lockNames.isEmpty()) {
            return null;
        }
        //获取锁对象
        RLock[] locks = new RLock[lockNames.size()];
        int i = 0;
        for (String lockName : lockNames) {
            String key = LOCK_TITLE + lockName;
            RLock lock = RedissonManager.getClient().getLock(key);
            locks[i] = lock;
            i++;
        }
        RLock lock = RedissonManager.getClient().getMultiLock(locks);
        //加锁，并且设置锁过期时间，防止死锁的产生
        lock.lock(leaseTime, unit);
        return lock;
    }

    /**
     * 释放锁，推荐本方法
     * 只能释放本线程锁，否则会报错
     *
     * @param lock 锁
     */
    public static void release(RLock lock) {
        if (lock != null) {
            //释放锁（解锁）
            lock.unlock();
        }
    }
}
